using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using ZoneFiveSoftware.Common.Data.Fitness;
using ZoneFiveSoftware.Common.Data.Measurement;
using ZoneFiveSoftware.Common.Visuals;
using FilteredStatistics.Common;
using FilteredStatistics.Common.Controller;
using FilteredStatistics.View;

namespace FilteredStatistics.Data
{
    class STZonesFilterCriteria : FilterCriteriaFacade
    {
        public enum STZoneTypes
        {
            Cadence = 0,
            Climb,
            HeartRate,
            Speed,
            Power,
            STZoneTypeCount
        }

        public STZonesFilterCriteria(IActivity activity, STZoneTypes type, IZoneCategory zoneCategory)
        {
            Activity = activity;
            m_Type = type;
            m_ZoneCategory = zoneCategory;

            PluginMain.ZoneCategoryListChanged += new PluginMain.ZoneCategoryChangedEventHandler(OnZoneCategoryChanged);

            BuildNamedZones();
        }

        private void OnZoneCategoryChanged(object sender, IZoneCategory category)
        {
            if (category == ZoneCategory)
            {
                BuildNamedZones();
            }
        }

#region FilterCriteriaFacade Members

        public override Guid ReferenceId
        {
            get { return new Guid(m_ZoneCategory.ReferenceId); }
        }

        public override String DisplayName
        {
            get
            {
                String result = String.Empty;

                switch (m_Type)
                {
                    case STZoneTypes.Cadence:
                        {
                            result += PluginView.GetLocalizedString("CadenceText");
                            break;
                        }
                    case STZoneTypes.Climb:
                        {
                            result += CommonResources.Text.LabelClimb;
                            break;
                        }
                    case STZoneTypes.HeartRate:
                        {
                            result += CommonResources.Text.LabelHeartRate;
                            break;
                        }
                    case STZoneTypes.Speed:
                        {
                            if (m_Activity != null && m_Activity.Category.SpeedUnits == Speed.Units.Pace)
                            {
                                result += CommonResources.Text.LabelPace;
                            }
                            else
                            {
                                result += CommonResources.Text.LabelSpeed;
                            }
                            break;
                        }
                    case STZoneTypes.Power:
                        {
                            result += CommonResources.Text.LabelPower;
                            break;
                        }
                }

                result += " (" + ZoneCategory.Name + ")";

                return result;
            }
        }

        public override IActivity Activity
        {
            set
            {
                if (m_Activity != value)
                {
                    m_Activity = value;

                    foreach (STZonesNamedZone namedZone in ConcreteNamedZones)
                    {
                        namedZone.Activity = m_Activity;
                    }
                }
            }
        }

        public override List<object> NamedZones
        {
            get { return m_NamedZones; }
        }

        public override bool IsTemplateOnly
        {
            get { return false; }
        }

        public override bool IsMainViewOnly
        {
            get { return false; }
        }

        public override bool IsSerializable
        {
            get { return true; }
        }

        public override void SerializeCriteria(Stream stream)
        {
            Serialize(stream);
        }

        public override UInt16 DataVersion
        {
            get { return Constants.CurrentVersion.VersionNumber; }
        }

        public override object DeserializeCriteria(Stream stream, UInt16 version)
        {
            DataVersion dataVersion = new DataVersion(version);

            try
            {
                Deserialize(stream, dataVersion);
            }
            catch
            {
                return null;
            }

            return this;
        }

        public override bool ValidateConsistency()
        {
            IZoneCategoryList zoneCategoryList = null;

            switch (STZoneType)
            {
                case STZoneTypes.Cadence:
                {
                    zoneCategoryList = PluginMain.GetApplication().Logbook.CadenceZones;
                    break;
                }
                case STZoneTypes.Climb:
                {
                    zoneCategoryList = PluginMain.GetApplication().Logbook.ClimbZones;
                    break;
                }
                case STZoneTypes.HeartRate:
                {
                    zoneCategoryList = PluginMain.GetApplication().Logbook.HeartRateZones;
                    break;
                }
                case STZoneTypes.Power:
                {
                    zoneCategoryList = PluginMain.GetApplication().Logbook.PowerZones;
                    break;
                }
                case STZoneTypes.Speed:
                {
                    zoneCategoryList = PluginMain.GetApplication().Logbook.SpeedZones;
                    break;
                }
            }

            Debug.Assert(zoneCategoryList != null);

            return zoneCategoryList.IndexOf(ZoneCategory) != -1;
        }

#endregion

#region IPluginSerializable members

        public override void Serialize(Stream stream)
        {
            base.Serialize(stream);
        }

#endregion

#region Deserialization methods

        public void Deserialize_V1(Stream stream, DataVersion version)
        {
            Debug.Assert(ZoneCategory != null);

            BuildNamedZones();
        }

#endregion

        public IActivity GetActivity()
        {
            return m_Activity;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            STZonesFilterCriteria criteria = obj as STZonesFilterCriteria;

            if (criteria != null)
            {
                return criteria.ZoneCategory == ZoneCategory;
            }

            return base.Equals(obj);
        }

        private void BuildNamedZones()
        {
            m_NamedZones.Clear();

            if (ZoneCategory != null)
            {
                foreach (INamedLowHighZone zone in ZoneCategory.Zones)
                {
                    m_NamedZones.Add(new STZonesNamedZone(this, m_Activity, zone));
                }
            }

            TriggerNamedZonesListChanged();
        }

        public IZoneCategory ZoneCategory
        {
            get { return m_ZoneCategory; }
            set { m_ZoneCategory = value; }
        }

        public STZoneTypes STZoneType
        {
            get { return m_Type; }
        }

        IActivity m_Activity = null;
        STZoneTypes m_Type = STZoneTypes.STZoneTypeCount;
        IZoneCategory m_ZoneCategory = null;
        List<object> m_NamedZones = new List<object>();
    }
}
